{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 2
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython2",
      "version": "2.7.6"
    },
    "colab": {
      "name": "train_shape.ipynb",
      "provenance": []
    },
    "accelerator": "GPU"
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "collapsed": true,
        "pycharm": {
          "name": "#%% md\n"
        },
        "id": "GI9KZ3F8TLSK",
        "colab_type": "text"
      },
      "source": [
        "# EfficientDet Training On A Custom Dataset\n",
        "\n",
        "\n",
        "\n",
        "<table align=\"left\"><td>\n",
        "  <a target=\"_blank\"  href=\"https://github.com/zylo117/Yet-Another-EfficientDet-Pytorch/blob/master/tutorial/train_shape.ipynb\">\n",
        "    <img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\" />View source on github\n",
        "  </a>\n",
        "</td><td>\n",
        "  <a target=\"_blank\"  href=\"https://colab.research.google.com/github/zylo117/Yet-Another-EfficientDet-Pytorch/blob/master/tutorial/train_shape.ipynb\">\n",
        "    <img width=32px src=\"https://www.tensorflow.org/images/colab_logo_32px.png\" />Run in Google Colab</a>\n",
        "</td></table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "collapsed": false,
        "pycharm": {
          "name": "#%% md\n"
        },
        "id": "67-3S5_VTLSL",
        "colab_type": "text"
      },
      "source": [
        "## This tutorial will show you how to train a custom dataset.\n",
        "\n",
        "## For the sake of simplicity, I generated a dataset of different shapes, like rectangles, triangles, circles.\n",
        "\n",
        "## Please enable GPU support to accelerate on notebook setting if you are using colab.\n",
        "\n",
        "### 0. Install Requirements"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "90laRz20TLSN",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 952
        },
        "outputId": "cdd3d988-ed26-429a-c1aa-e5b8c6ee534c"
      },
      "source": [
        "!pip install pycocotools numpy==1.16.0 opencv-python tqdm tensorboard tensorboardX pyyaml webcolors matplotlib\n",
        "!pip install torch==1.4.0\n",
        "!pip install torchvision==0.5.0"
      ],
      "execution_count": 1,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Requirement already satisfied: pycocotools in /usr/local/lib/python3.6/dist-packages (2.0.0)\n",
            "Collecting numpy==1.16.0\n",
            "\u001b[?25l  Downloading https://files.pythonhosted.org/packages/7b/74/54c5f9bb9bd4dae27a61ec1b39076a39d359b3fb7ba15da79ef23858a9d8/numpy-1.16.0-cp36-cp36m-manylinux1_x86_64.whl (17.3MB)\n",
            "\u001b[K     |████████████████████████████████| 17.3MB 215kB/s \n",
            "\u001b[?25hRequirement already satisfied: opencv-python in /usr/local/lib/python3.6/dist-packages (4.1.2.30)\n",
            "Requirement already satisfied: tqdm in /usr/local/lib/python3.6/dist-packages (4.41.1)\n",
            "Requirement already satisfied: tensorboard in /usr/local/lib/python3.6/dist-packages (2.2.2)\n",
            "Collecting tensorboardX\n",
            "\u001b[?25l  Downloading https://files.pythonhosted.org/packages/35/f1/5843425495765c8c2dd0784a851a93ef204d314fc87bcc2bbb9f662a3ad1/tensorboardX-2.0-py2.py3-none-any.whl (195kB)\n",
            "\u001b[K     |████████████████████████████████| 204kB 38.5MB/s \n",
            "\u001b[?25hRequirement already satisfied: pyyaml in /usr/local/lib/python3.6/dist-packages (3.13)\n",
            "Collecting webcolors\n",
            "  Downloading https://files.pythonhosted.org/packages/12/05/3350559de9714b202e443a9e6312937341bd5f79f4e4f625744295e7dd17/webcolors-1.11.1-py3-none-any.whl\n",
            "Requirement already satisfied: matplotlib in /usr/local/lib/python3.6/dist-packages (3.2.1)\n",
            "Requirement already satisfied: wheel>=0.26; python_version >= \"3\" in /usr/local/lib/python3.6/dist-packages (from tensorboard) (0.34.2)\n",
            "Requirement already satisfied: requests<3,>=2.21.0 in /usr/local/lib/python3.6/dist-packages (from tensorboard) (2.23.0)\n",
            "Requirement already satisfied: tensorboard-plugin-wit>=1.6.0 in /usr/local/lib/python3.6/dist-packages (from tensorboard) (1.6.0.post3)\n",
            "Requirement already satisfied: setuptools>=41.0.0 in /usr/local/lib/python3.6/dist-packages (from tensorboard) (47.1.1)\n",
            "Requirement already satisfied: six>=1.10.0 in /usr/local/lib/python3.6/dist-packages (from tensorboard) (1.12.0)\n",
            "Requirement already satisfied: google-auth-oauthlib<0.5,>=0.4.1 in /usr/local/lib/python3.6/dist-packages (from tensorboard) (0.4.1)\n",
            "Requirement already satisfied: protobuf>=3.6.0 in /usr/local/lib/python3.6/dist-packages (from tensorboard) (3.10.0)\n",
            "Requirement already satisfied: werkzeug>=0.11.15 in /usr/local/lib/python3.6/dist-packages (from tensorboard) (1.0.1)\n",
            "Requirement already satisfied: absl-py>=0.4 in /usr/local/lib/python3.6/dist-packages (from tensorboard) (0.9.0)\n",
            "Requirement already satisfied: markdown>=2.6.8 in /usr/local/lib/python3.6/dist-packages (from tensorboard) (3.2.2)\n",
            "Requirement already satisfied: grpcio>=1.24.3 in /usr/local/lib/python3.6/dist-packages (from tensorboard) (1.29.0)\n",
            "Requirement already satisfied: google-auth<2,>=1.6.3 in /usr/local/lib/python3.6/dist-packages (from tensorboard) (1.17.2)\n",
            "Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.6/dist-packages (from matplotlib) (0.10.0)\n",
            "Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib) (2.4.7)\n",
            "Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib) (1.2.0)\n",
            "Requirement already satisfied: python-dateutil>=2.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib) (2.8.1)\n",
            "Requirement already satisfied: idna<3,>=2.5 in /usr/local/lib/python3.6/dist-packages (from requests<3,>=2.21.0->tensorboard) (2.9)\n",
            "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.6/dist-packages (from requests<3,>=2.21.0->tensorboard) (2020.4.5.2)\n",
            "Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /usr/local/lib/python3.6/dist-packages (from requests<3,>=2.21.0->tensorboard) (1.24.3)\n",
            "Requirement already satisfied: chardet<4,>=3.0.2 in /usr/local/lib/python3.6/dist-packages (from requests<3,>=2.21.0->tensorboard) (3.0.4)\n",
            "Requirement already satisfied: requests-oauthlib>=0.7.0 in /usr/local/lib/python3.6/dist-packages (from google-auth-oauthlib<0.5,>=0.4.1->tensorboard) (1.3.0)\n",
            "Requirement already satisfied: importlib-metadata; python_version < \"3.8\" in /usr/local/lib/python3.6/dist-packages (from markdown>=2.6.8->tensorboard) (1.6.1)\n",
            "Requirement already satisfied: pyasn1-modules>=0.2.1 in /usr/local/lib/python3.6/dist-packages (from google-auth<2,>=1.6.3->tensorboard) (0.2.8)\n",
            "Requirement already satisfied: rsa<5,>=3.1.4; python_version >= \"3\" in /usr/local/lib/python3.6/dist-packages (from google-auth<2,>=1.6.3->tensorboard) (4.6)\n",
            "Requirement already satisfied: cachetools<5.0,>=2.0.0 in /usr/local/lib/python3.6/dist-packages (from google-auth<2,>=1.6.3->tensorboard) (4.1.0)\n",
            "Requirement already satisfied: oauthlib>=3.0.0 in /usr/local/lib/python3.6/dist-packages (from requests-oauthlib>=0.7.0->google-auth-oauthlib<0.5,>=0.4.1->tensorboard) (3.1.0)\n",
            "Requirement already satisfied: zipp>=0.5 in /usr/local/lib/python3.6/dist-packages (from importlib-metadata; python_version < \"3.8\"->markdown>=2.6.8->tensorboard) (3.1.0)\n",
            "Requirement already satisfied: pyasn1<0.5.0,>=0.4.6 in /usr/local/lib/python3.6/dist-packages (from pyasn1-modules>=0.2.1->google-auth<2,>=1.6.3->tensorboard) (0.4.8)\n",
            "\u001b[31mERROR: umap-learn 0.4.4 has requirement numpy>=1.17, but you'll have numpy 1.16.0 which is incompatible.\u001b[0m\n",
            "\u001b[31mERROR: datascience 0.10.6 has requirement folium==0.2.1, but you'll have folium 0.8.3 which is incompatible.\u001b[0m\n",
            "\u001b[31mERROR: albumentations 0.1.12 has requirement imgaug<0.2.7,>=0.2.5, but you'll have imgaug 0.2.9 which is incompatible.\u001b[0m\n",
            "Installing collected packages: numpy, tensorboardX, webcolors\n",
            "  Found existing installation: numpy 1.18.5\n",
            "    Uninstalling numpy-1.18.5:\n",
            "      Successfully uninstalled numpy-1.18.5\n",
            "Successfully installed numpy-1.16.0 tensorboardX-2.0 webcolors-1.11.1\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "display_data",
          "data": {
            "application/vnd.colab-display-data+json": {
              "pip_warning": {
                "packages": [
                  "numpy"
                ]
              }
            }
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "collapsed": false,
        "pycharm": {
          "name": "#%% md\n"
        },
        "id": "-R5C4DaETLSS",
        "colab_type": "text"
      },
      "source": [
        "### 1. Prepare Custom Dataset/Pretrained Weights (Skip this part if you already have datasets and weights of your own)"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "JmCQj3rhTLSS",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 921
        },
        "outputId": "0842b828-a6bf-4bd9-82ac-cc97d12aa9dd"
      },
      "source": [
        "import os\n",
        "import sys\n",
        "if \"projects\" not in os.getcwd():\n",
        "  !git clone --depth 1 https://github.com/zylo117/Yet-Another-EfficientDet-Pytorch\n",
        "  os.chdir('Yet-Another-EfficientDet-Pytorch')\n",
        "  sys.path.append('.')\n",
        "else:\n",
        "  !git pull\n",
        "\n",
        "# download and unzip dataset\n",
        "! mkdir datasets\n",
        "! wget https://github.com/zylo117/Yet-Another-EfficientDet-Pytorch/releases/download/1.1/dataset_shape.tar.gz\n",
        "! tar xzf dataset_shape.tar.gz\n",
        "\n",
        "# download pretrained weights\n",
        "! mkdir weights\n",
        "! wget https://github.com/zylo117/Yet-Another-EfficientDet-Pytorch/releases/download/1.0/efficientdet-d0.pth -O weights/efficientdet-d0.pth\n",
        "\n",
        "# prepare project file projects/shape.yml\n",
        "# showing its contents here\n",
        "! cat projects/shape.yml"
      ],
      "execution_count": 2,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Cloning into 'Yet-Another-EfficientDet-Pytorch'...\n",
            "remote: Enumerating objects: 43, done.\u001b[K\n",
            "remote: Counting objects: 100% (43/43), done.\u001b[K\n",
            "remote: Compressing objects: 100% (39/39), done.\u001b[K\n",
            "remote: Total 43 (delta 3), reused 22 (delta 1), pack-reused 0\u001b[K\n",
            "Unpacking objects: 100% (43/43), done.\n",
            "--2020-06-18 02:41:28--  https://github.com/zylo117/Yet-Another-EfficientDet-Pytorch/releases/download/1.1/dataset_shape.tar.gz\n",
            "Resolving github.com (github.com)... 140.82.118.4\n",
            "Connecting to github.com (github.com)|140.82.118.4|:443... connected.\n",
            "HTTP request sent, awaiting response... 302 Found\n",
            "Location: https://github-production-release-asset-2e65be.s3.amazonaws.com/253385242/b4de2a00-7e55-11ea-89ac-50cd8071e6ce?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20200618%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20200618T024128Z&X-Amz-Expires=300&X-Amz-Signature=2584a0dac8cf892da56cdf5d4845131e4346c765c3b6afae35879931b65f4e4e&X-Amz-SignedHeaders=host&actor_id=0&repo_id=253385242&response-content-disposition=attachment%3B%20filename%3Ddataset_shape.tar.gz&response-content-type=application%2Foctet-stream [following]\n",
            "--2020-06-18 02:41:28--  https://github-production-release-asset-2e65be.s3.amazonaws.com/253385242/b4de2a00-7e55-11ea-89ac-50cd8071e6ce?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20200618%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20200618T024128Z&X-Amz-Expires=300&X-Amz-Signature=2584a0dac8cf892da56cdf5d4845131e4346c765c3b6afae35879931b65f4e4e&X-Amz-SignedHeaders=host&actor_id=0&repo_id=253385242&response-content-disposition=attachment%3B%20filename%3Ddataset_shape.tar.gz&response-content-type=application%2Foctet-stream\n",
            "Resolving github-production-release-asset-2e65be.s3.amazonaws.com (github-production-release-asset-2e65be.s3.amazonaws.com)... 52.217.37.92\n",
            "Connecting to github-production-release-asset-2e65be.s3.amazonaws.com (github-production-release-asset-2e65be.s3.amazonaws.com)|52.217.37.92|:443... connected.\n",
            "HTTP request sent, awaiting response... 200 OK\n",
            "Length: 5770263 (5.5M) [application/octet-stream]\n",
            "Saving to: ‘dataset_shape.tar.gz’\n",
            "\n",
            "dataset_shape.tar.g 100%[===================>]   5.50M  7.61MB/s    in 0.7s    \n",
            "\n",
            "2020-06-18 02:41:29 (7.61 MB/s) - ‘dataset_shape.tar.gz’ saved [5770263/5770263]\n",
            "\n",
            "--2020-06-18 02:41:34--  https://github.com/zylo117/Yet-Another-EfficientDet-Pytorch/releases/download/1.0/efficientdet-d0.pth\n",
            "Resolving github.com (github.com)... 140.82.118.4\n",
            "Connecting to github.com (github.com)|140.82.118.4|:443... connected.\n",
            "HTTP request sent, awaiting response... 302 Found\n",
            "Location: https://github-production-release-asset-2e65be.s3.amazonaws.com/253385242/9b9d2100-791d-11ea-80b2-d35899cf95fe?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20200618%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20200618T024135Z&X-Amz-Expires=300&X-Amz-Signature=c4d613ce694cbb959c9b5bec39f9e7ae9e57e90262ffee0f8d7c8c847fa1f4e5&X-Amz-SignedHeaders=host&actor_id=0&repo_id=253385242&response-content-disposition=attachment%3B%20filename%3Defficientdet-d0.pth&response-content-type=application%2Foctet-stream [following]\n",
            "--2020-06-18 02:41:35--  https://github-production-release-asset-2e65be.s3.amazonaws.com/253385242/9b9d2100-791d-11ea-80b2-d35899cf95fe?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20200618%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20200618T024135Z&X-Amz-Expires=300&X-Amz-Signature=c4d613ce694cbb959c9b5bec39f9e7ae9e57e90262ffee0f8d7c8c847fa1f4e5&X-Amz-SignedHeaders=host&actor_id=0&repo_id=253385242&response-content-disposition=attachment%3B%20filename%3Defficientdet-d0.pth&response-content-type=application%2Foctet-stream\n",
            "Resolving github-production-release-asset-2e65be.s3.amazonaws.com (github-production-release-asset-2e65be.s3.amazonaws.com)... 52.216.82.216\n",
            "Connecting to github-production-release-asset-2e65be.s3.amazonaws.com (github-production-release-asset-2e65be.s3.amazonaws.com)|52.216.82.216|:443... connected.\n",
            "HTTP request sent, awaiting response... 200 OK\n",
            "Length: 15862583 (15M) [application/octet-stream]\n",
            "Saving to: ‘weights/efficientdet-d0.pth’\n",
            "\n",
            "weights/efficientde 100%[===================>]  15.13M  15.1MB/s    in 1.0s    \n",
            "\n",
            "2020-06-18 02:41:36 (15.1 MB/s) - ‘weights/efficientdet-d0.pth’ saved [15862583/15862583]\n",
            "\n",
            "project_name: shape  # also the folder name of the dataset that under data_path folder\n",
            "train_set: train\n",
            "val_set: val\n",
            "num_gpus: 1\n",
            "\n",
            "# mean and std in RGB order, actually this part should remain unchanged as long as your dataset is similar to coco.\n",
            "mean: [0.485, 0.456, 0.406]\n",
            "std: [0.229, 0.224, 0.225]\n",
            "\n",
            "# this anchor is adapted to the dataset\n",
            "anchors_scales: '[2 ** 0, 2 ** (1.0 / 3.0), 2 ** (2.0 / 3.0)]'\n",
            "anchors_ratios: '[(1.0, 1.0), (1.4, 0.7), (0.7, 1.4)]'\n",
            "\n",
            "obj_list: ['rectangle', 'circle']"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "collapsed": false,
        "id": "7Q2onXNZTLSV",
        "colab_type": "text"
      },
      "source": [
        "### 2. Training"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "a-eznEu5TLSW",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 1000
        },
        "outputId": "0a2b3a08-39e1-45c0-8c4c-6a48c22611ba"
      },
      "source": [
        "# consider this is a simple dataset, train head will be enough.\n",
        "! python train.py -c 0 -p shape --head_only True --lr 1e-3 --batch_size 32 --load_weights weights/efficientdet-d0.pth  --num_epochs 50 --save_interval 100\n",
        "\n",
        "# the loss will be high at first\n",
        "# don't panic, be patient,\n",
        "# just wait for a little bit longer"
      ],
      "execution_count": 3,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "loading annotations into memory...\n",
            "Done (t=0.02s)\n",
            "creating index...\n",
            "index created!\n",
            "loading annotations into memory...\n",
            "Done (t=0.00s)\n",
            "creating index...\n",
            "index created!\n",
            "[Warning] Ignoring Error(s) in loading state_dict for EfficientDetBackbone:\n",
            "\tsize mismatch for classifier.header.pointwise_conv.conv.weight: copying a param with shape torch.Size([810, 64, 1, 1]) from checkpoint, the shape in current model is torch.Size([18, 64, 1, 1]).\n",
            "\tsize mismatch for classifier.header.pointwise_conv.conv.bias: copying a param with shape torch.Size([810]) from checkpoint, the shape in current model is torch.Size([18]).\n",
            "[Warning] Don't panic if you see this, this might be because you load a pretrained weights with different number of classes. The rest of the weights should be loaded already.\n",
            "[Info] loaded weights: efficientdet-d0.pth, resuming checkpoint from step: 0\n",
            "[Info] freezed backbone\n",
            "Step: 27. Epoch: 0/50. Iteration: 28/28. Cls loss: 26.29772. Reg loss: 0.01289. Total loss: 26.31061: 100% 28/28 [00:46<00:00,  1.66s/it]\n",
            "Val. Epoch: 0/50. Classification loss: 12.20426. Regression loss: 0.01610. Total loss: 12.22037\n",
            "Step: 55. Epoch: 1/50. Iteration: 28/28. Cls loss: 3.66639. Reg loss: 0.01443. Total loss: 3.68082: 100% 28/28 [00:46<00:00,  1.65s/it]\n",
            "Val. Epoch: 1/50. Classification loss: 3.10739. Regression loss: 0.01396. Total loss: 3.12135\n",
            "Step: 83. Epoch: 2/50. Iteration: 28/28. Cls loss: 2.61804. Reg loss: 0.01078. Total loss: 2.62881: 100% 28/28 [00:46<00:00,  1.66s/it]\n",
            "Val. Epoch: 2/50. Classification loss: 1.99466. Regression loss: 0.01278. Total loss: 2.00744\n",
            "Step: 111. Epoch: 3/50. Iteration: 28/28. Cls loss: 1.44927. Reg loss: 0.01206. Total loss: 1.46133: 100% 28/28 [00:46<00:00,  1.66s/it]\n",
            "Val. Epoch: 3/50. Classification loss: 1.42343. Regression loss: 0.01165. Total loss: 1.43508\n",
            "Step: 139. Epoch: 4/50. Iteration: 28/28. Cls loss: 1.44247. Reg loss: 0.01195. Total loss: 1.45442: 100% 28/28 [00:46<00:00,  1.67s/it]\n",
            "Val. Epoch: 4/50. Classification loss: 1.15894. Regression loss: 0.01040. Total loss: 1.16934\n",
            "Step: 167. Epoch: 5/50. Iteration: 28/28. Cls loss: 0.96989. Reg loss: 0.01074. Total loss: 0.98064: 100% 28/28 [00:46<00:00,  1.66s/it]\n",
            "Val. Epoch: 5/50. Classification loss: 0.94637. Regression loss: 0.00966. Total loss: 0.95603\n",
            "Step: 195. Epoch: 6/50. Iteration: 28/28. Cls loss: 0.90316. Reg loss: 0.00981. Total loss: 0.91297: 100% 28/28 [00:46<00:00,  1.66s/it]\n",
            "Val. Epoch: 6/50. Classification loss: 0.80626. Regression loss: 0.00944. Total loss: 0.81570\n",
            "Step: 223. Epoch: 7/50. Iteration: 28/28. Cls loss: 0.83105. Reg loss: 0.01052. Total loss: 0.84157: 100% 28/28 [00:46<00:00,  1.67s/it]\n",
            "Val. Epoch: 7/50. Classification loss: 0.69999. Regression loss: 0.00907. Total loss: 0.70907\n",
            "Step: 251. Epoch: 8/50. Iteration: 28/28. Cls loss: 0.68107. Reg loss: 0.01090. Total loss: 0.69197: 100% 28/28 [00:46<00:00,  1.68s/it]\n",
            "Val. Epoch: 8/50. Classification loss: 0.62273. Regression loss: 0.00883. Total loss: 0.63156\n",
            "Step: 279. Epoch: 9/50. Iteration: 28/28. Cls loss: 0.63515. Reg loss: 0.01228. Total loss: 0.64743: 100% 28/28 [00:46<00:00,  1.67s/it]\n",
            "Val. Epoch: 9/50. Classification loss: 0.55948. Regression loss: 0.00851. Total loss: 0.56798\n",
            "Step: 307. Epoch: 10/50. Iteration: 28/28. Cls loss: 0.50954. Reg loss: 0.01053. Total loss: 0.52007: 100% 28/28 [00:47<00:00,  1.68s/it]\n",
            "Val. Epoch: 10/50. Classification loss: 0.50945. Regression loss: 0.00836. Total loss: 0.51781\n",
            "Step: 335. Epoch: 11/50. Iteration: 28/28. Cls loss: 0.52033. Reg loss: 0.00733. Total loss: 0.52766: 100% 28/28 [00:46<00:00,  1.67s/it]\n",
            "Val. Epoch: 11/50. Classification loss: 0.46788. Regression loss: 0.00800. Total loss: 0.47587\n",
            "Step: 363. Epoch: 12/50. Iteration: 28/28. Cls loss: 0.49584. Reg loss: 0.00927. Total loss: 0.50511: 100% 28/28 [00:47<00:00,  1.68s/it]\n",
            "Val. Epoch: 12/50. Classification loss: 0.43143. Regression loss: 0.00792. Total loss: 0.43935\n",
            "Step: 391. Epoch: 13/50. Iteration: 28/28. Cls loss: 0.45326. Reg loss: 0.00893. Total loss: 0.46219: 100% 28/28 [00:46<00:00,  1.67s/it]\n",
            "Val. Epoch: 13/50. Classification loss: 0.40211. Regression loss: 0.00764. Total loss: 0.40974\n",
            "Step: 419. Epoch: 14/50. Iteration: 28/28. Cls loss: 0.40421. Reg loss: 0.00882. Total loss: 0.41303: 100% 28/28 [00:47<00:00,  1.68s/it]\n",
            "Val. Epoch: 14/50. Classification loss: 0.37800. Regression loss: 0.00736. Total loss: 0.38537\n",
            "Step: 447. Epoch: 15/50. Iteration: 28/28. Cls loss: 0.38576. Reg loss: 0.00615. Total loss: 0.39191: 100% 28/28 [00:47<00:00,  1.68s/it]\n",
            "Val. Epoch: 15/50. Classification loss: 0.35435. Regression loss: 0.00746. Total loss: 0.36181\n",
            "Step: 475. Epoch: 16/50. Iteration: 28/28. Cls loss: 0.38551. Reg loss: 0.01182. Total loss: 0.39733: 100% 28/28 [00:46<00:00,  1.68s/it]\n",
            "Val. Epoch: 16/50. Classification loss: 0.33601. Regression loss: 0.00737. Total loss: 0.34338\n",
            "Step: 499. Epoch: 17/50. Iteration: 24/28. Cls loss: 0.35644. Reg loss: 0.00668. Total loss: 0.36312:  82% 23/28 [00:41<00:05,  1.15s/it]checkpoint...\n",
            "Step: 503. Epoch: 17/50. Iteration: 28/28. Cls loss: 0.35166. Reg loss: 0.00812. Total loss: 0.35978: 100% 28/28 [00:46<00:00,  1.67s/it]\n",
            "Val. Epoch: 17/50. Classification loss: 0.31798. Regression loss: 0.00725. Total loss: 0.32523\n",
            "Step: 531. Epoch: 18/50. Iteration: 28/28. Cls loss: 0.35137. Reg loss: 0.01101. Total loss: 0.36238: 100% 28/28 [00:46<00:00,  1.67s/it]\n",
            "Val. Epoch: 18/50. Classification loss: 0.30364. Regression loss: 0.00718. Total loss: 0.31082\n",
            "Step: 559. Epoch: 19/50. Iteration: 28/28. Cls loss: 0.29872. Reg loss: 0.00653. Total loss: 0.30525: 100% 28/28 [00:46<00:00,  1.68s/it]\n",
            "Val. Epoch: 19/50. Classification loss: 0.29044. Regression loss: 0.00733. Total loss: 0.29776\n",
            "Step: 587. Epoch: 20/50. Iteration: 28/28. Cls loss: 0.30086. Reg loss: 0.00810. Total loss: 0.30896: 100% 28/28 [00:46<00:00,  1.67s/it]\n",
            "Val. Epoch: 20/50. Classification loss: 0.27783. Regression loss: 0.00728. Total loss: 0.28511\n",
            "Step: 615. Epoch: 21/50. Iteration: 28/28. Cls loss: 0.34610. Reg loss: 0.00809. Total loss: 0.35419: 100% 28/28 [00:46<00:00,  1.67s/it]\n",
            "Val. Epoch: 21/50. Classification loss: 0.26462. Regression loss: 0.00711. Total loss: 0.27173\n",
            "Step: 643. Epoch: 22/50. Iteration: 28/28. Cls loss: 0.28175. Reg loss: 0.00807. Total loss: 0.28981: 100% 28/28 [00:46<00:00,  1.68s/it]\n",
            "Val. Epoch: 22/50. Classification loss: 0.25356. Regression loss: 0.00716. Total loss: 0.26071\n",
            "Step: 671. Epoch: 23/50. Iteration: 28/28. Cls loss: 0.27373. Reg loss: 0.00875. Total loss: 0.28248: 100% 28/28 [00:46<00:00,  1.67s/it]\n",
            "Val. Epoch: 23/50. Classification loss: 0.24350. Regression loss: 0.00737. Total loss: 0.25087\n",
            "Step: 699. Epoch: 24/50. Iteration: 28/28. Cls loss: 0.25727. Reg loss: 0.00815. Total loss: 0.26542: 100% 28/28 [00:46<00:00,  1.67s/it]\n",
            "Val. Epoch: 24/50. Classification loss: 0.23465. Regression loss: 0.00712. Total loss: 0.24177\n",
            "Step: 727. Epoch: 25/50. Iteration: 28/28. Cls loss: 0.23017. Reg loss: 0.01109. Total loss: 0.24125: 100% 28/28 [00:46<00:00,  1.67s/it]\n",
            "Val. Epoch: 25/50. Classification loss: 0.22561. Regression loss: 0.00716. Total loss: 0.23277\n",
            "Step: 755. Epoch: 26/50. Iteration: 28/28. Cls loss: 0.22237. Reg loss: 0.00591. Total loss: 0.22828: 100% 28/28 [00:46<00:00,  1.68s/it]\n",
            "Val. Epoch: 26/50. Classification loss: 0.21848. Regression loss: 0.00694. Total loss: 0.22542\n",
            "Step: 783. Epoch: 27/50. Iteration: 28/28. Cls loss: 0.25054. Reg loss: 0.00917. Total loss: 0.25971: 100% 28/28 [00:46<00:00,  1.68s/it]\n",
            "Val. Epoch: 27/50. Classification loss: 0.21120. Regression loss: 0.00699. Total loss: 0.21819\n",
            "Step: 811. Epoch: 28/50. Iteration: 28/28. Cls loss: 0.22907. Reg loss: 0.00829. Total loss: 0.23737: 100% 28/28 [00:47<00:00,  1.68s/it]\n",
            "Val. Epoch: 28/50. Classification loss: 0.20494. Regression loss: 0.00701. Total loss: 0.21195\n",
            "Step: 839. Epoch: 29/50. Iteration: 28/28. Cls loss: 0.26674. Reg loss: 0.00852. Total loss: 0.27526: 100% 28/28 [00:46<00:00,  1.67s/it]\n",
            "Val. Epoch: 29/50. Classification loss: 0.19854. Regression loss: 0.00670. Total loss: 0.20523\n",
            "Step: 867. Epoch: 30/50. Iteration: 28/28. Cls loss: 0.19063. Reg loss: 0.00593. Total loss: 0.19656: 100% 28/28 [00:46<00:00,  1.67s/it]\n",
            "Val. Epoch: 30/50. Classification loss: 0.19303. Regression loss: 0.00679. Total loss: 0.19982\n",
            "Step: 895. Epoch: 31/50. Iteration: 28/28. Cls loss: 0.23191. Reg loss: 0.00678. Total loss: 0.23869: 100% 28/28 [00:46<00:00,  1.67s/it]\n",
            "Val. Epoch: 31/50. Classification loss: 0.18698. Regression loss: 0.00675. Total loss: 0.19373\n",
            "Step: 923. Epoch: 32/50. Iteration: 28/28. Cls loss: 0.18452. Reg loss: 0.00685. Total loss: 0.19137: 100% 28/28 [00:46<00:00,  1.68s/it]\n",
            "Val. Epoch: 32/50. Classification loss: 0.18236. Regression loss: 0.00679. Total loss: 0.18915\n",
            "Step: 951. Epoch: 33/50. Iteration: 28/28. Cls loss: 0.20275. Reg loss: 0.00758. Total loss: 0.21033: 100% 28/28 [00:47<00:00,  1.68s/it]\n",
            "Val. Epoch: 33/50. Classification loss: 0.17713. Regression loss: 0.00692. Total loss: 0.18405\n",
            "Step: 979. Epoch: 34/50. Iteration: 28/28. Cls loss: 0.18318. Reg loss: 0.00577. Total loss: 0.18895: 100% 28/28 [00:47<00:00,  1.68s/it]\n",
            "Val. Epoch: 34/50. Classification loss: 0.17203. Regression loss: 0.00657. Total loss: 0.17860\n",
            "Step: 999. Epoch: 35/50. Iteration: 20/28. Cls loss: 0.18499. Reg loss: 0.00838. Total loss: 0.19337:  68% 19/28 [00:37<00:10,  1.17s/it]checkpoint...\n",
            "Step: 1007. Epoch: 35/50. Iteration: 28/28. Cls loss: 0.18154. Reg loss: 0.00630. Total loss: 0.18784: 100% 28/28 [00:46<00:00,  1.68s/it]\n",
            "Val. Epoch: 35/50. Classification loss: 0.16700. Regression loss: 0.00666. Total loss: 0.17366\n",
            "Step: 1035. Epoch: 36/50. Iteration: 28/28. Cls loss: 0.18250. Reg loss: 0.00611. Total loss: 0.18861: 100% 28/28 [00:47<00:00,  1.68s/it]\n",
            "Val. Epoch: 36/50. Classification loss: 0.16309. Regression loss: 0.00679. Total loss: 0.16989\n",
            "Step: 1063. Epoch: 37/50. Iteration: 28/28. Cls loss: 0.15622. Reg loss: 0.00623. Total loss: 0.16245: 100% 28/28 [00:46<00:00,  1.67s/it]\n",
            "Val. Epoch: 37/50. Classification loss: 0.15933. Regression loss: 0.00666. Total loss: 0.16599\n",
            "Step: 1091. Epoch: 38/50. Iteration: 28/28. Cls loss: 0.14960. Reg loss: 0.00556. Total loss: 0.15515: 100% 28/28 [00:46<00:00,  1.67s/it]\n",
            "Val. Epoch: 38/50. Classification loss: 0.15517. Regression loss: 0.00683. Total loss: 0.16201\n",
            "Step: 1119. Epoch: 39/50. Iteration: 28/28. Cls loss: 0.17928. Reg loss: 0.00657. Total loss: 0.18585: 100% 28/28 [00:46<00:00,  1.67s/it]\n",
            "Val. Epoch: 39/50. Classification loss: 0.15171. Regression loss: 0.00657. Total loss: 0.15828\n",
            "Step: 1147. Epoch: 40/50. Iteration: 28/28. Cls loss: 0.17436. Reg loss: 0.00468. Total loss: 0.17904: 100% 28/28 [00:46<00:00,  1.67s/it]\n",
            "Val. Epoch: 40/50. Classification loss: 0.14942. Regression loss: 0.00667. Total loss: 0.15609\n",
            "Step: 1175. Epoch: 41/50. Iteration: 28/28. Cls loss: 0.16362. Reg loss: 0.00781. Total loss: 0.17143: 100% 28/28 [00:46<00:00,  1.67s/it]\n",
            "Val. Epoch: 41/50. Classification loss: 0.14597. Regression loss: 0.00686. Total loss: 0.15283\n",
            "Step: 1203. Epoch: 42/50. Iteration: 28/28. Cls loss: 0.17241. Reg loss: 0.00837. Total loss: 0.18078: 100% 28/28 [00:46<00:00,  1.67s/it]\n",
            "Val. Epoch: 42/50. Classification loss: 0.14308. Regression loss: 0.00662. Total loss: 0.14969\n",
            "Step: 1231. Epoch: 43/50. Iteration: 28/28. Cls loss: 0.17507. Reg loss: 0.00802. Total loss: 0.18309: 100% 28/28 [00:46<00:00,  1.68s/it]\n",
            "Val. Epoch: 43/50. Classification loss: 0.13933. Regression loss: 0.00666. Total loss: 0.14599\n",
            "Step: 1259. Epoch: 44/50. Iteration: 28/28. Cls loss: 0.17234. Reg loss: 0.00580. Total loss: 0.17814: 100% 28/28 [00:46<00:00,  1.68s/it]\n",
            "Val. Epoch: 44/50. Classification loss: 0.13601. Regression loss: 0.00647. Total loss: 0.14247\n",
            "Step: 1287. Epoch: 45/50. Iteration: 28/28. Cls loss: 0.16627. Reg loss: 0.00595. Total loss: 0.17222: 100% 28/28 [00:46<00:00,  1.67s/it]\n",
            "Val. Epoch: 45/50. Classification loss: 0.13402. Regression loss: 0.00653. Total loss: 0.14055\n",
            "Step: 1315. Epoch: 46/50. Iteration: 28/28. Cls loss: 0.17035. Reg loss: 0.00682. Total loss: 0.17717: 100% 28/28 [00:46<00:00,  1.68s/it]\n",
            "Val. Epoch: 46/50. Classification loss: 0.13196. Regression loss: 0.00638. Total loss: 0.13834\n",
            "Step: 1343. Epoch: 47/50. Iteration: 28/28. Cls loss: 0.12934. Reg loss: 0.00527. Total loss: 0.13461: 100% 28/28 [00:46<00:00,  1.68s/it]\n",
            "Val. Epoch: 47/50. Classification loss: 0.12878. Regression loss: 0.00664. Total loss: 0.13542\n",
            "Step: 1371. Epoch: 48/50. Iteration: 28/28. Cls loss: 0.12199. Reg loss: 0.00390. Total loss: 0.12589: 100% 28/28 [00:46<00:00,  1.67s/it]\n",
            "Val. Epoch: 48/50. Classification loss: 0.12630. Regression loss: 0.00681. Total loss: 0.13311\n",
            "Step: 1399. Epoch: 49/50. Iteration: 28/28. Cls loss: 0.13337. Reg loss: 0.00523. Total loss: 0.13859: 100% 28/28 [00:46<00:00,  1.67s/it]\n",
            "Val. Epoch: 49/50. Classification loss: 0.12423. Regression loss: 0.00635. Total loss: 0.13058\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "collapsed": false,
        "id": "05mjrGRETLSZ",
        "colab_type": "text"
      },
      "source": [
        "### 3. Evaluation"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "9yzNyaSxTLSZ",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 493
        },
        "outputId": "f38ef0e7-bf30-428a-cf93-43e43a60fdae"
      },
      "source": [
        "#get latest weight file\n",
        "%cd logs/shape\n",
        "weight_file = !ls -Art | grep efficientdet\n",
        "%cd ../..\n",
        "\n",
        "#uncomment the next line to specify a weight file\n",
        "#weight_file[-1] = 'efficientdet-d0_49_1400.pth'\n",
        "\n",
        "! python coco_eval.py -c 0 -p shape -w \"logs/shape/{weight_file[-1]}\""
      ],
      "execution_count": 4,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "running coco-style evaluation on project shape, weights logs/shape/efficientdet-d0_49_1400.pth...\n",
            "loading annotations into memory...\n",
            "Done (t=0.00s)\n",
            "creating index...\n",
            "index created!\n",
            "100% 100/100 [00:08<00:00, 11.80it/s]\n",
            "Loading and preparing results...\n",
            "DONE (t=0.63s)\n",
            "creating index...\n",
            "index created!\n",
            "BBox\n",
            "Running per image evaluation...\n",
            "Evaluate annotation type *bbox*\n",
            "DONE (t=1.46s).\n",
            "Accumulating evaluation results...\n",
            "DONE (t=0.14s).\n",
            " Average Precision  (AP) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = 0.781\n",
            " Average Precision  (AP) @[ IoU=0.50      | area=   all | maxDets=100 ] = 0.947\n",
            " Average Precision  (AP) @[ IoU=0.75      | area=   all | maxDets=100 ] = 0.868\n",
            " Average Precision  (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = -1.000\n",
            " Average Precision  (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.794\n",
            " Average Precision  (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.740\n",
            " Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=  1 ] = 0.470\n",
            " Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets= 10 ] = 0.841\n",
            " Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = 0.843\n",
            " Average Recall     (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = -1.000\n",
            " Average Recall     (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.850\n",
            " Average Recall     (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.819\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "collapsed": false,
        "pycharm": {
          "name": "#%% md\n"
        },
        "id": "zhV3bNF3TLSc",
        "colab_type": "text"
      },
      "source": [
        "### 4. Visualize"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "uEDHMAIJTLSc",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 269
        },
        "outputId": "cbeedcbd-cd4f-41a6-e0d6-875398081cd8"
      },
      "source": [
        "import torch\n",
        "from torch.backends import cudnn\n",
        "\n",
        "from backbone import EfficientDetBackbone\n",
        "import cv2\n",
        "import matplotlib.pyplot as plt\n",
        "import numpy as np\n",
        "\n",
        "from efficientdet.utils import BBoxTransform, ClipBoxes\n",
        "from utils.utils import preprocess, invert_affine, postprocess\n",
        "\n",
        "compound_coef = 0\n",
        "force_input_size = None  # set None to use default size\n",
        "img_path = 'datasets/shape/val/999.jpg'\n",
        "\n",
        "threshold = 0.2\n",
        "iou_threshold = 0.2\n",
        "\n",
        "use_cuda = True\n",
        "use_float16 = False\n",
        "cudnn.fastest = True\n",
        "cudnn.benchmark = True\n",
        "\n",
        "obj_list = ['rectangle', 'circle']\n",
        "\n",
        "# tf bilinear interpolation is different from any other's, just make do\n",
        "input_sizes = [512, 640, 768, 896, 1024, 1280, 1280, 1536]\n",
        "input_size = input_sizes[compound_coef] if force_input_size is None else force_input_size\n",
        "ori_imgs, framed_imgs, framed_metas = preprocess(img_path, max_size=input_size)\n",
        "\n",
        "if use_cuda:\n",
        "    x = torch.stack([torch.from_numpy(fi).cuda() for fi in framed_imgs], 0)\n",
        "else:\n",
        "    x = torch.stack([torch.from_numpy(fi) for fi in framed_imgs], 0)\n",
        "\n",
        "x = x.to(torch.float32 if not use_float16 else torch.float16).permute(0, 3, 1, 2)\n",
        "\n",
        "model = EfficientDetBackbone(compound_coef=compound_coef, num_classes=len(obj_list),\n",
        "\n",
        "                             # replace this part with your project's anchor config\n",
        "                             ratios=[(1.0, 1.0), (1.4, 0.7), (0.7, 1.4)],\n",
        "                             scales=[2 ** 0, 2 ** (1.0 / 3.0), 2 ** (2.0 / 3.0)])\n",
        "\n",
        "model.load_state_dict(torch.load('logs/shape/'+weight_file[-1]))\n",
        "model.requires_grad_(False)\n",
        "model.eval()\n",
        "\n",
        "if use_cuda:\n",
        "    model = model.cuda()\n",
        "if use_float16:\n",
        "    model = model.half()\n",
        "\n",
        "with torch.no_grad():\n",
        "    features, regression, classification, anchors = model(x)\n",
        "\n",
        "    regressBoxes = BBoxTransform()\n",
        "    clipBoxes = ClipBoxes()\n",
        "\n",
        "    out = postprocess(x,\n",
        "                      anchors, regression, classification,\n",
        "                      regressBoxes, clipBoxes,\n",
        "                      threshold, iou_threshold)\n",
        "\n",
        "out = invert_affine(framed_metas, out)\n",
        "\n",
        "for i in range(len(ori_imgs)):\n",
        "    if len(out[i]['rois']) == 0:\n",
        "        continue\n",
        "    ori_imgs[i] = ori_imgs[i].copy()\n",
        "    for j in range(len(out[i]['rois'])):\n",
        "        (x1, y1, x2, y2) = out[i]['rois'][j].astype(np.int)\n",
        "        cv2.rectangle(ori_imgs[i], (x1, y1), (x2, y2), (255, 255, 0), 2)\n",
        "        obj = obj_list[out[i]['class_ids'][j]]\n",
        "        score = float(out[i]['scores'][j])\n",
        "\n",
        "        cv2.putText(ori_imgs[i], '{}, {:.3f}'.format(obj, score),\n",
        "                    (x1, y1 + 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5,\n",
        "                    (255, 255, 0), 1)\n",
        "\n",
        "        plt.imshow(ori_imgs[i])\n",
        "\n"
      ],
      "execution_count": 5,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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\n",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "tags": [],
            "needs_background": "light"
          }
        }
      ]
    }
  ]
}
